#pragma once

#include <iostream>
#include <vector>
#include <unordered_map>
#include <map>
#include <algorithm>

#include <time.h>
#include <assert.h>

#include <thread>
#include <mutex>
#include <atomic>
#ifdef _WIN32
	#include<Windows.h>
#else

#endif 
#include"ObjectPool.h"


const int Pagenum = 129;
 const int hash_size = 208;
 const int byte_MAX = 256*1024;
 const int Page_shift = 13;
using std::cout;
using std::endl;
#ifdef _WIN64
	typedef unsigned long long PAGE_ID;
#elif _WIN32
	typedef size_t PAGE_ID;
#elif 
	//LINUX XIA
#endif // _WIN64



inline static void* SystemAlloc(size_t kpage)
{
#ifdef _WIN32
	void* ptr = VirtualAlloc(0, kpage << 13, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
#else
	// linux下brk mmap等
#endif

	if (ptr == nullptr)
		throw std::bad_alloc();

	return ptr;
}

inline static void SystemFree(void* ptr)
{
#ifdef _WIN32
	VirtualFree(ptr, 0, MEM_RELEASE);
#else

#endif

}

static void*& Nextobj(void* obj)
{
	return *(void**)obj;
}

class freelist
{
public:
	void Push(void* obj)
	{
		//ͷCHA
		Nextobj(obj) = _freelist;
		_freelist = obj;
		++size;
	}
	void* Pop()
	{
		//头删并获得删之前的结点
		assert(_freelist);
		void* obj = _freelist;
		_freelist = Nextobj(obj);
		--size;
		return obj;
	}
	void PushRange(void* start, void* end,size_t n)
	{
		Nextobj(end) =_freelist;
		_freelist = start;
		size += n;
	}
	void PopRange(void*& start, void*& end, size_t n)
	{
	 start = _freelist;
		 end = start;
		for (int i = 0; i < n - 1; i++)
		{
			end = Nextobj(end);
		}
		_freelist = Nextobj(end);
		Nextobj(end) = nullptr;
		size -= n;
	}
	bool Empety()
	{
		return _freelist == nullptr;
	}
	size_t& maxsize()
	{
		return _MAXSIZE;
	}
	size_t Size()
	{
		return size;
	}
private:
	void* _freelist = nullptr;
	size_t _MAXSIZE = 1;
	size_t size = 0;
};

class sizeclass
{
public:
	//这样浪费的内存最多在10%左右

	//申请字节[1,128]					对齐方式为8字节对齐		下标映射位置[0,16)
	//申请字节[128+1,1024]			对齐的字节数位16位			下表映射位置为[16,72)
	//申请字节[1024+1,8*1024]		    对齐的字节数位128位		下表映射位置为[72,128)
	//申请字节[8*1024+1,64*1024]     对齐的数字为1024位		    下表映射位置为[128,184)
	//申请字节[64*1024+1,256*1024]   对齐的数字为8*1024位		下表映射位置为[184，208)
	/*static inline void _Rundup(size_t size, size_t alignnum)
	{
		size_t alignsize;
		if (size % alignnum != 0)
		{
			alignsize = (size / alignnum + 1) * alignnum;
		}
		else
		{
			alignsize = size;
		}
	}*/
	static inline size_t _Rundup(size_t size, size_t alignnum)
	{
		return ((size + alignnum - 1) & ~(alignnum - 1));
	}
	static inline size_t Rundup(size_t size)
	{
		if (size <=128)
		{
			return _Rundup(size, 8);
		}
		else if (size <= 1024)
		{
			return _Rundup(size, 16);

		}
		else if (size <= 1024)
		{
			return _Rundup(size, 128);

		}
		else if (size <= 1024)
		{
			return _Rundup(size, 1024);

		}
		else if (size <= 1024)
		{
			return _Rundup(size, 8*1024);

		}
		else
		{
			
			return _Rundup(size,1<<Page_shift);
		}
	}

	/*static inline size_t _Index(size_t size, size_t alignnum)
	{
		size_t pos;
		if (size % alignnum != 0)
		{
			pos = size / alignnum ;
		}
		else
		{
			pos = size / alignnum-1;
		}
		return pos;
	}*/
	static inline size_t _Index(size_t bytes, size_t align_shift)
	{
		return ((bytes + (1 << align_shift) - 1) >> align_shift) - 1;
	}
	static inline size_t Index(size_t size)
	{
		const int nums[4] = { 16,56,56,56 };
		if (size <= 128)
		{
			return _Index(size, 3);
		}
		else if (size <= 1024)
		{
			return _Index(size, 4) + nums[0];

		}
		else if (size <= 1024)
		{
			return _Index(size, 7) + nums[0] + nums[1];


		}
		else if (size <= 1024)
		{
			return _Index(size, 10) + nums[0] + nums[1] + nums[2];


		}
		else if (size <= 1024)
		{
			return _Index(size, 13) + nums[0] + nums[1] + nums[2] + nums[3];


		}
		else
		{
			assert(false);
			return -1;
		}
	}
	static size_t NumMoveSize(size_t size)
	{
		size_t num = SIZE_MAX / size;
		if (num < 2)num = 2;

		if (num > 512)num = 512;
		return num;
	}

	static size_t PageMoveSize(size_t size)
	{
		size_t bytes = NumMoveSize(size);
		size_t npage = bytes * size;
		size_t num = npage >> Page_shift;
		if ( num== 0)
			num = 1;
		return num;
	}
};


//管理大块内存span切好的内存
struct Span
{
	PAGE_ID _pageid = 0;//页的起始地址

	size_t _n = 0;//页的个数

	Span* _prev = nullptr;//双向链表
	Span* _next = nullptr;

	size_t _usecount = 0;
	void* freelist = nullptr;

	bool _isuse = false;
};

//带头双相链表
class Spanlist
{
public:
	bool Empety()
	{
		return _head->_next == _head;
	}
	Span* Popfront()
	{
		Span* next = _head->_next;
		Erase(next);
		return next;
	}
	Spanlist()
	{
		static ObjectPool<Span> spanPool;
		//_head = new Span;
		_head = spanPool.New();

		_head->_next = _head;
		_head->_prev = _head;
	}
	Span* begin()
	{
		return _head->_next;
	}
	Span* end()
	{
		return _head;
	}
	void Insert(Span* pos, Span* newspan)
	{
		assert(pos);
		assert(newspan);
		Span* prev = pos->_prev;
		prev->_next = newspan;
		newspan->_prev = prev;
		newspan->_next = pos;
		pos->_prev = pos;
	}
	void Pushfront(Span*obj)
	{
		Insert(begin(), obj);
	}
	void Erase(Span*pos)
	{
		assert(pos);
		assert(pos != _head);
		Span* prev = pos->_prev;
		Span* next = pos->_next;
		prev->_next = pos;
		next->_prev = prev;

	}
private:
	Span* _head=nullptr;
public:
	std::mutex _mtx;
};
